package com.naiterui.ehp.bs.b2c.order.service.impl.logistics;

import cn.hutool.core.collection.CollectionUtil;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.naiterui.ehp.bp.support.utils.JsonMapper;
import com.naiterui.ehp.bp.utils.encypt.MD5;
import com.naiterui.ehp.bp.utils.net.RestHttpUtil;
import com.naiterui.ehp.bs.b2c.order.bo.LogisticsInfoBO;
import com.naiterui.ehp.bs.b2c.order.bo.LogisticsTraceLogBO;
import com.naiterui.ehp.bs.b2c.order.vo.logistics.BaseResponse;
import com.naiterui.ehp.bs.b2c.order.vo.logistics.best.BestRequest;
import com.naiterui.ehp.bs.b2c.order.vo.logistics.best.tracequery.request.BestMailNos;
import com.naiterui.ehp.bs.b2c.order.vo.logistics.best.tracequery.request.BestTraceQueryRequest;
import com.naiterui.ehp.bs.b2c.order.vo.logistics.best.tracequery.response.BestTrace;
import com.naiterui.ehp.bs.b2c.order.vo.logistics.best.tracequery.response.BestTraceLogs;
import com.naiterui.ehp.bs.b2c.order.vo.logistics.best.tracequery.response.BestTraceQueryResponse;
import com.naiterui.ehp.bs.b2c.order.vo.logistics.best.tracequery.response.BestTraces;

import lombok.extern.slf4j.Slf4j;

/**
 * 百世快递
 */
@Slf4j
@Service("huitongkuaidi")
public class BestLogisticsTraceServiceImpl extends AbstractLogisticsTraceService<BestRequest> {

    private final String partnerId = "65441";

    private final String partnerKey = "p5h7waktf8a4";

    /**
     * 服务地址
     */
    private final String serviceUrl = "http://edi-q9.ns.800best.com/kd/api/process";

    @Override
    public Map<String, LogisticsInfoBO> getTrace(List<String> deliveryIds) {
        BestTraceQueryRequest traceQueryRequest = new BestTraceQueryRequest();
        BestMailNos mailNos = new BestMailNos();
        mailNos.setMailNo(deliveryIds);
        traceQueryRequest.setMailNos(mailNos);
        Map<String, LogisticsInfoBO> logisticsTraceInfoMap = Maps.newHashMap();
        try {
            BestTraceQueryResponse traceQueryResponse = this.execute(traceQueryRequest, new ParameterizedTypeReference<BestTraceQueryResponse>() {
            });
            if (traceQueryResponse == null) {
                return logisticsTraceInfoMap;
            }
            Map<String, BestTraces> collectMap = Optional.of(traceQueryResponse.getTraceLogs())
                                                         .orElse(Lists.newArrayList())
                                                         .stream()
                                                         .collect(Collectors.toMap(BestTraceLogs::getMailNo, BestTraceLogs::getTraces));

            collectMap.forEach((deliveryId, traces) -> {
                if (traces == null) {
                    return;
                }
                LogisticsInfoBO logisticsInfo = new LogisticsInfoBO();
                logisticsInfo.setDeliveryId(deliveryId);
                List<LogisticsTraceLogBO> traceLogs = traces.getTrace()
                                                            .stream()
                                                            .map(m -> LogisticsTraceLogBO.builder()
                                                                                         .time(m.getAcceptTime())
                                                                                         .address(m.getAcceptAddress())
                                                                                         .content(m.getRemark())
                                                                                         .build()).collect(Collectors.toList());
                logisticsInfo.setTraceLogs(traceLogs);
                if (CollectionUtil.isEmpty(traceLogs)) {
                    logisticsInfo.setStatus(LogisticsInfoBO.STATUS_NONE);
                } else {
                    //找到物流状态
                    List<String> collect = traces.getTrace().stream().map(BestTrace::getScanType).collect(Collectors.toList());
                    if (collect.contains("签收") || collect.contains("用户提货") || collect.contains("代理点签收") || collect.contains("特殊签收")) {
                        logisticsInfo.setStatus(LogisticsInfoBO.STATUS_RECEIVED);
                    } else if (collect.contains("收件")) {
                        logisticsInfo.setStatus(LogisticsInfoBO.STATUS_PICKUP);
                    } else if (collect.contains("拒收")) {
                        logisticsInfo.setStatus(LogisticsInfoBO.STATUS_REJECT);
                    } else {
                        logisticsInfo.setStatus(LogisticsInfoBO.STATUS_ONWAY);
                    }
                }
                logisticsTraceInfoMap.put(deliveryId, logisticsInfo);
            });
            log.info("查询物流:{} 返回结果:{}", deliveryIds, logisticsTraceInfoMap);
        } catch (IOException e) {
            log.error("json转换失败", e);
        }
        return logisticsTraceInfoMap;
    }


    @Override
    protected <E extends BaseResponse> E execute(BestRequest bestRequest, ParameterizedTypeReference<E> responseTypeReference) throws IOException {
        String bizData = JsonMapper.toJson(bestRequest);
        Map<String, String> params = Maps.newHashMap();
        params.put("serviceType", bestRequest.getServiceType());
        params.put("bizData", bizData);
        params.put("partnerID", this.partnerId);
        params.put("sign", MD5.md5(bizData + this.partnerKey));
        ResponseEntity<String> responseEntity = RestHttpUtil.post()
                                                            .url(this.serviceUrl)
                                                            .paramMap(params)
                                                            .execute(new ParameterizedTypeReference<String>() {
                                                            });
        return JsonMapper.toObject(responseEntity.getBody(), responseTypeReference);
    }

}
